Skip to content

fix(upgrade): refresh installer-written agent surfaces after a binary upgrade (#1238)#1239

Merged
colbymchenry merged 3 commits into
colbymchenry:mainfrom
xuing:upgrade-refresh-installed-surfaces
Jul 10, 2026
Merged

fix(upgrade): refresh installer-written agent surfaces after a binary upgrade (#1238)#1239
colbymchenry merged 3 commits into
colbymchenry:mainfrom
xuing:upgrade-refresh-installed-surfaces

Conversation

@xuing

@xuing xuing commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Fixes #1238.

Problem

codegraph upgrade updates the binary, but never revisits what earlier installs wrote into the agents. On a machine using CodeGraph since 0.9.x, every upgrade through 1.3.1 left the marker-fenced CLAUDE.md / AGENTS.md sections exactly as the 0.9.x installer wrote them: a nine-tool decision table telling agents to reach for codegraph_context first — a tool 1.0.0 removed — and for six other tools that no longer appear on the default MCP surface. Agents follow the file, get "unknown tool", and conclude CodeGraph is broken. Full timeline in #1238.

Every write in the install path is already an idempotent, self-healing upsert (the pre-#529 long-block heal, the pre-0.8 hook cleanup, the pre-#207 local-MCP migration) — but nothing ever invokes it on upgrade, so all that healing only reaches users who happen to re-run codegraph install by hand.

Approach

Extends the precedent already in the upgrade path: runUpgrade self-heals the Claude prompt hook after a successful swap. This PR does the same for the rest of the installed surfaces, with one twist the prompt hook didn't need: the instruction templates are baked into the binary, so the heal must be executed by the new binary — the still-running old process would only rewrite its own stale copy, the exact staleness being healed.

  • codegraph install --refresh — a non-interactive sweep (same shape as uninstallTargets, exposed and unit-tested the same way) that re-runs install() for every target that is already configured. Never a first install: unconfigured agents are skipped, permissions aren't written (autoAllow: false), and the prompt hook is left as the user chose it (promptHook: undefined). Sweeps global + local unless --location narrows it.
  • codegraph upgrade spawns codegraph install --refresh after a successful binary swap — PATH resolves to the fresh install at that point. Gated on codegraph being resolvable (an npm-local install isn't), opt-out via CODEGRAPH_NO_INSTALL_REFRESH=1, and never fatal to the upgrade.

Nothing changes on a machine that's already current: every underlying write is the targets' own byte-compare upsert, so the sweep reports unchanged across the board and prints one quiet line.

What it looks like

$ codegraph upgrade
…
✓ Upgrade complete.
Refreshing agent instruction sections and config written by previous versions…
  Claude Code: refreshed /home/user/.claude/CLAUDE.md
  Codex CLI: refreshed /home/user/.codex/AGENTS.md

On an already-current machine:

$ codegraph install --refresh
All configured agent surfaces are already current.

Tests

  • 6 new runUpgrade orchestration tests: the refresh is spawned last (after the swap, so the new binary writes); Windows runs the .cmd launcher through cmd.exe; skipped when codegraph isn't on PATH; skipped by the kill-switch; a failing refresh warns without failing the upgrade; no refresh after a failed upgrade.
  • 4 new refreshTargets sweep tests: rewrites a planted stale block and reports refreshed; never performs a first install; preserves a hand-trimmed permissions list; second sweep is all-unchanged.
  • Targeted installer/upgrade suites: 193 passed / 0 failed; TypeScript build passed.
  • Manual e2e: fresh build, fake $HOME, install -t claude -l global -y → plant the 0.9.x section → install --refresh rewrites it to the current template → second --refresh reports already-current.

Not in this PR

Old codex installers also wrote per-tool approval_mode blocks ([mcp_servers.codegraph.tools.*]) that can reference tools which no longer exist; install() doesn't own those keys today, so the sweep doesn't clean them. That would be a target-level cleanup in the codex target, same pattern as the existing legacy-hook cleanup — happy to follow up if wanted.

🤖 Proudly generated using Fable 5, and reviewed with GPT5.6 sol.

… upgrade

codegraph upgrade swapped the binary but never revisited what earlier
installs wrote into CLAUDE.md / AGENTS.md / GEMINI.md and the agent
configs, so sections written by a pre-1.0 installer kept teaching agents
a multi-tool surface (including tools that no longer exist) months of
releases later. The install path already self-heals everything it owns,
but nothing ever called it on upgrade.

- codegraph install --refresh: non-interactive sweep that re-runs
  install() for already-configured targets only — never a first
  install; permissions and prompt-hook choices are preserved.
- codegraph upgrade spawns it via the freshly-installed binary after a
  successful swap (the still-running old process would only rewrite its
  own stale template). Gated on PATH resolution and the
  CODEGRAPH_NO_INSTALL_REFRESH=1 kill-switch; never fatal to the
  upgrade.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 10, 2026 02:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR ensures that after codegraph upgrade swaps in a new binary, any agent-facing surfaces previously written by older installers (marker-fenced instruction blocks and MCP entries) are refreshed so they match the tool surface and templates of the newly-installed version.

Changes:

  • Add a refresh-only sweep (codegraph install --refresh) that re-runs per-target install() only for already-configured targets, preserving permissions and prompt-hook choices.
  • Invoke that sweep automatically at the end of a successful codegraph upgrade (non-fatal, PATH-gated, opt-out via CODEGRAPH_NO_INSTALL_REFRESH=1).
  • Add unit tests covering upgrade orchestration and refresh sweep behavior/idempotency.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/upgrade/index.ts Spawns codegraph install --refresh after successful upgrades (with platform-specific Windows handling and kill-switch).
src/installer/index.ts Introduces refreshTargets() and RefreshReport to refresh already-configured targets only.
src/bin/codegraph.ts Adds codegraph install --refresh CLI flag and wires it to refreshTargets().
CHANGELOG.md Documents the new upgrade-time refresh behavior and manual install --refresh usage.
tests/upgrade.test.ts Adds orchestration tests verifying refresh spawn timing, Windows invocation, gating, kill-switch, and non-fatal failure behavior.
tests/installer-targets.test.ts Adds refresh sweep tests for stale block rewrite, “no first install”, permissions preservation, and idempotency.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/installer/index.ts
colbymchenry added a commit that referenced this pull request Jul 10, 2026
… resolved version after every upgrade (#1238, #1071) (#1245)

Two fixes to make `codegraph upgrade` trustworthy in the terminal it ran in:

1. detectInstallMethod checked the bundle layout before the node_modules
   path check, but the npm thin-installer's per-platform package IS a
   complete bundle inside node_modules — so every npm install misdetected
   as a standalone bundle, and upgrade curled install.sh into ~/.codegraph:
   a second install that never wins the PATH race against npm's shim,
   leaving `codegraph -v` permanently on the old version. Path-based
   checks (_npx, node_modules) now win over layout sniffing, so npm
   installs upgrade through npm again, in place.

2. After a successful swap, runUpgrade now probes the PATH-resolved
   `codegraph --version` and reports the real outcome: a green
   confirmation that this terminal already serves the new version, a
   loud shadow warning naming the fix (`which -a codegraph`) on
   mismatch, or the old soft new-terminal hint only when the probe is
   inconclusive. Replaces the unconditional "open a new terminal if the
   version looks unchanged" hedge. Skipped for npm-local installs, whose
   binary PATH never serves.

Companion to #1239: the misdetection also broke its post-upgrade
`install --refresh` for npm users (the spawn resolved the stale shim).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…he version probe

Conflict resolution after colbymchenry#1245 landed, plus the integration it called for:
runUpgrade now runs the PATH version probe first and skips spawning
`codegraph install --refresh` on a 'mismatch' — a shadowed stale binary
would rewrite the agent surfaces with the very templates the refresh
exists to heal. The skip logs a pointer to run the refresh manually once
the PATH is fixed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@colbymchenry colbymchenry merged commit 386bff0 into colbymchenry:main Jul 10, 2026
1 check passed
@colbymchenry

Copy link
Copy Markdown
Owner

Merged — thanks @xuing, this was a well-built fix: the refresh-only semantics, the new-binary spawn, and the test coverage all held up under validation (unit suites + live e2e on macOS, Linux/Docker, and Windows).

Note on the final commit: rather than ask you to rebase, I resolved the post-#1245 conflict directly on your branch and wired the two PRs together — runUpgrade now runs #1245's PATH version probe first and skips spawning codegraph install --refresh when the probe detects a shadowed stale install (the spawn would execute the old binary, rewriting the agent surfaces with the very templates the refresh exists to heal). Mismatch logs a pointer to run codegraph install --refresh manually once the PATH is fixed. Everything else is yours as written.

Both fixes ship in the next release. Your follow-up offer on the legacy codex approval_mode blocks is welcome, too.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upgrading CodeGraph leaves old agent instructions in place

3 participants